package com.waikuai.shop.controller;

import com.waikuai.shop.common.result.Result;
import com.waikuai.shop.entity.ShoppingCart;
import com.waikuai.shop.service.ShoppingCartService;
import com.waikuai.shop.service.UserService;
import com.waikuai.shop.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;

/**
 * 购物车控制器
 * @author waikuai
 */
@Slf4j
@RestController
@RequestMapping("/cart")
@RequiredArgsConstructor
@Validated
public class ShoppingCartController {

    private final ShoppingCartService shoppingCartService;
    private final UserService userService;
    private final JwtUtil jwtUtil;

    /**
     * 获取购物车列表
     */
    @GetMapping
    public Result<List<ShoppingCart>> getCartList(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            List<ShoppingCart> cartList = shoppingCartService.getUserCart(userId);
            log.info("获取购物车列表成功，用户ID: {}, 商品数量: {}", userId, cartList.size());
            return Result.success("获取购物车列表成功", cartList);
        } catch (Exception e) {
            log.error("获取购物车列表失败: {}", e.getMessage(), e);
            return Result.error("获取购物车列表失败");
        }
    }

    /**
     * 添加商品到购物车
     */
    @PostMapping("/add")
    public Result<String> addToCart(
            @RequestParam @NotNull Long productId,
            @RequestParam @NotNull Integer quantity,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.addToCart(userId, productId, quantity);
            if (result) {
                log.info("添加商品到购物车成功，用户ID: {}, 商品ID: {}, 数量: {}", userId, productId, quantity);
                return Result.success("添加商品到购物车成功");
            } else {
                return Result.error("添加商品到购物车失败，请检查商品库存");
            }
        } catch (Exception e) {
            log.error("添加商品到购物车失败: {}", e.getMessage(), e);
            return Result.error("添加商品到购物车失败");
        }
    }

    /**
     * 更新购物车商品数量
     */
    @PutMapping("/update")
    public Result<String> updateQuantity(
            @RequestParam @NotNull Long productId,
            @RequestParam @NotNull Integer quantity,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.updateCartItemQuantity(userId, productId, quantity);
            if (result) {
                log.info("更新购物车商品数量成功，用户ID: {}, 商品ID: {}, 数量: {}", userId, productId, quantity);
                return Result.success("更新购物车商品数量成功");
            } else {
                return Result.error("更新购物车商品数量失败，请检查商品库存");
            }
        } catch (Exception e) {
            log.error("更新购物车商品数量失败: {}", e.getMessage(), e);
            return Result.error("更新购物车商品数量失败");
        }
    }

    /**
     * 删除购物车商品
     */
    @DeleteMapping("/remove")
    public Result<String> removeFromCart(
            @RequestParam @NotNull Long productId,
            HttpServletRequest request) {
        try {
            log.info("开始删除购物车商品，商品ID: {}", productId);
            Long userId = getCurrentUserId(request);
            log.info("获取用户ID成功: {}", userId);
            
            boolean result = shoppingCartService.removeFromCart(userId, productId);
            if (result) {
                log.info("删除购物车商品成功，用户ID: {}, 商品ID: {}", userId, productId);
                return Result.success("删除购物车商品成功");
            } else {
                log.warn("删除购物车商品失败，删除记录数为0，用户ID: {}, 商品ID: {}，可能商品不存在或已被删除", userId, productId);
                // 返回成功，因为从业务角度来说，删除一个不存在的商品也可以视为成功
                // 或者返回404，表示资源不存在
                return Result.notFound("购物车中不存在该商品");
            }
        } catch (RuntimeException e) {
            log.error("删除购物车商品失败，商品ID: {}, 异常类型: {}, 异常消息: {}", 
                    productId, e.getClass().getSimpleName(), e.getMessage(), e);
            return Result.error("删除购物车商品失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("删除购物车商品发生未知异常，商品ID: {}, 异常类型: {}, 异常消息: {}", 
                    productId, e.getClass().getSimpleName(), e.getMessage(), e);
            return Result.error("删除购物车商品失败");
        }
    }

    /**
     * 批量删除购物车商品
     */
    @DeleteMapping("/batch-remove")
    public Result<String> batchRemoveFromCart(
            @RequestParam @NotNull List<Long> productIds,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.batchRemoveFromCart(userId, productIds);
            if (result) {
                log.info("批量删除购物车商品成功，用户ID: {}, 商品数量: {}", userId, productIds.size());
                return Result.success("批量删除购物车商品成功");
            } else {
                return Result.error("批量删除购物车商品失败");
            }
        } catch (Exception e) {
            log.error("批量删除购物车商品失败: {}", e.getMessage(), e);
            return Result.error("批量删除购物车商品失败");
        }
    }

    /**
     * 清空购物车
     */
    @DeleteMapping("/clear")
    public Result<String> clearCart(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.clearCart(userId);
            if (result) {
                log.info("清空购物车成功，用户ID: {}", userId);
                return Result.success("清空购物车成功");
            } else {
                return Result.error("清空购物车失败");
            }
        } catch (Exception e) {
            log.error("清空购物车失败: {}", e.getMessage(), e);
            return Result.error("清空购物车失败");
        }
    }

    /**
     * 更新商品选中状态
     */
    @PutMapping("/select")
    public Result<String> updateSelectedStatus(
            @RequestParam @NotNull Long productId,
            @RequestParam @NotNull Boolean selected,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.updateSelectedStatus(userId, productId, selected);
            if (result) {
                log.info("更新商品选中状态成功，用户ID: {}, 商品ID: {}, 选中状态: {}", userId, productId, selected);
                return Result.success("更新商品选中状态成功");
            } else {
                return Result.error("更新商品选中状态失败");
            }
        } catch (Exception e) {
            log.error("更新商品选中状态失败: {}", e.getMessage(), e);
            return Result.error("更新商品选中状态失败");
        }
    }

    /**
     * 全选/全不选
     */
    @PutMapping("/select-all")
    public Result<String> updateAllSelectedStatus(
            @RequestParam @NotNull Boolean selected,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shoppingCartService.updateAllSelectedStatus(userId, selected);
            if (result) {
                log.info("更新全选状态成功，用户ID: {}, 选中状态: {}", userId, selected);
                return Result.success("更新全选状态成功");
            } else {
                return Result.error("更新全选状态失败");
            }
        } catch (Exception e) {
            log.error("更新全选状态失败: {}", e.getMessage(), e);
            return Result.error("更新全选状态失败");
        }
    }

    /**
     * 计算选中商品总金额
     */
    @GetMapping("/total")
    public Result<BigDecimal> calculateTotal(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            BigDecimal total = shoppingCartService.calculateSelectedTotal(userId);
            log.info("计算选中商品总金额成功，用户ID: {}, 总金额: {}", userId, total);
            return Result.success("计算总金额成功", total);
        } catch (Exception e) {
            log.error("计算选中商品总金额失败: {}", e.getMessage(), e);
            return Result.error("计算总金额失败");
        }
    }

    /**
     * 获取购物车商品数量统计
     */
    @GetMapping("/count")
    public Result<Integer> getCartCount(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Integer count = shoppingCartService.countCartItems(userId);
            log.info("获取购物车商品数量成功，用户ID: {}, 数量: {}", userId, count);
            return Result.success("获取购物车商品数量成功", count);
        } catch (Exception e) {
            log.error("获取购物车商品数量失败: {}", e.getMessage(), e);
            return Result.error("获取购物车商品数量失败");
        }
    }

    /**
     * 获取选中的购物车商品
     */
    @GetMapping("/selected")
    public Result<List<ShoppingCart>> getSelectedItems(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            List<ShoppingCart> selectedItems = shoppingCartService.getSelectedItems(userId);
            log.info("获取选中购物车商品成功，用户ID: {}, 数量: {}", userId, selectedItems.size());
            return Result.success("获取选中购物车商品成功", selectedItems);
        } catch (Exception e) {
            log.error("获取选中购物车商品失败: {}", e.getMessage(), e);
            return Result.error("获取选中购物车商品失败");
        }
    }

    /**
     * 获取当前登录用户ID
     * 优先使用Spring Security认证，如果不可用则从HTTP Token中获取
     */
    private Long getCurrentUserId() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() != null) {
                Object principal = authentication.getPrincipal();
                if (principal instanceof UserDetails) {
                    UserDetails userDetails = (UserDetails) principal;
                    String username = userDetails.getUsername();
                    
                    com.waikuai.shop.entity.User user = userService.findByUsername(username);
                    if (user != null) {
                        return user.getId();
                    }
                }
            }
        } catch (Exception e) {
            log.debug("从Spring Security获取用户ID失败，尝试从Token获取: {}", e.getMessage());
        }
        
        throw new RuntimeException("用户未登录，请先登录");
    }

    /**
     * 从HTTP请求中获取用户ID（备用方案）
     */
    private Long getUserIdFromToken(HttpServletRequest request) {
        try {
            String bearerToken = request.getHeader("Authorization");
            if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
                String token = bearerToken.substring(7);
                
                if (!jwtUtil.validateTokenFormat(token)) {
                    log.warn("Token格式无效");
                    return null;
                }
                
                if (jwtUtil.isTokenExpired(token)) {
                    log.warn("Token已过期");
                    return null;
                }
                
                Long userId = jwtUtil.getUserIdFromToken(token);
                if (userId != null) {
                    log.debug("从Token中获取用户ID成功: {}", userId);
                    return userId;
                }
            }
        } catch (Exception e) {
            log.error("从Token中获取用户ID失败: {}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取当前登录用户ID（兼容多种方式）
     */
    private Long getCurrentUserId(HttpServletRequest request) {
        try {
            return getCurrentUserId();
        } catch (RuntimeException e) {
            Long userId = getUserIdFromToken(request);
            if (userId != null) {
                return userId;
            }
            log.warn("获取用户ID失败: Spring Security和Token都不可用");
            throw new RuntimeException("用户未登录，请先登录");
        }
    }
}
